'use strict';
const Controller = require('egg').Controller;
const crypto = require('crypto');
const process = require('process');


class InfringementCheckController extends Controller {
  /**
     *@api {post} /infringement-check 侵权检测(异步)
     *@apiName infringement
     *@apiDescription 检测包含哪些侵权词
     *@apiGroup Tortious
     *@apiParam {string}  [callback_url]  检测结果回调地址
     *@apiParam {string}  [categorie_id] 类别ID 不选即所有分类
     *@apiParam {string}  [source]    站点源
     *@apiParam {array[object]}  texts 待检测文本列表
     *@apiParam {string}  texts.key 待检测文本标识
     *@apiParam {string}  texts.text 待检测文本内容
     *@apiSuccess {int} errcode  错误码
     *@apiSuccess {string} message 提示语
     *@apiSuccess {object} data  --
     *@apiSuccess {string} data.sign 参数签名
     */
  async infringementCheck() {
    const { ctx, service } = this;
    const body = await ctx.multipartToJson() || ctx.request.body;
    let { callback_url, categorie_id, source, texts, by_word, test_callback } = body;
    try {
      texts = JSON.parse(texts);
    } catch (err) {
      // ctx.logger.error('texts incorrect format', texts);
    }
    if (Number(by_word) === 0) {
      by_word = false;
    } else {
      by_word = true;
    }
    if (!Array.isArray(texts)) {
      return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'texts must be array' });
    }
    if (!source) {
      source = ctx.app.config.erpSite;
    }
    if (body.hasOwnProperty('categorie_id') && await service.tortious.existsTortious(categorie_id)) {
      return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'current categorie_id does not exist' });
    }
    for (const text of texts) {
      if (!(text.key && typeof text.key === 'string')) {
        return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'text.key must be string' });
      }
      if (!(text.text && typeof text.text === 'string')) {
        return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'text.text must be string' });
      }
    }
    const detectionData = { test_callback, callback_url, categorie_id, source, texts, by_word };
    const sign = crypto.createHash('md5').update(JSON.stringify(detectionData)).digest('hex');
    detectionData.sign = sign;
    await ctx.app.queue.add('tortious-worker', detectionData, {
      removeOnComplete: true,
      jobId: sign,
    });
    ctx.json({ errcode: this.ctx.ERRCODE.NORMAL, message: 'success', data: { sign } });
  }

  /**
     *@api {post} /infringement-check-multi 多分类侵权检测(异步)
     *@apiName multi-infringement
     *@apiDescription 多分类检测包含哪些侵权词
     *@apiGroup Tortious
     *@apiParam {int}  [by_word=1]  是否按词检测,即按词检测即词的两端加一个空格去匹配 <br/> 1:按词组 &emsp; 0：不安词组
     *@apiParam {string}  [callback_url]  检测结果回调地址
     *@apiParam {array[string]}  categorie_ids 类别ID列表
     *@apiParam {string}  [source]    站点源
     *@apiParam {array[object]}  texts 待检测文本列表
     *@apiParam {string}  texts.key 待检测文本标识
     *@apiParam {string}  texts.text 待检测文本内容
     *@apiSuccess {int} errcode  错误码
     *@apiSuccess {string} message 提示语
     *@apiSuccess {object} data  --
     *@apiSuccess {string} data.sign 参数签名
     */
  async multiInfringementCheck() {
    const { ctx, service } = this;
    const body = await ctx.multipartToJson() || ctx.request.body;
    let { callback_url, categorie_ids, source, texts, by_word } = body;
    try {
      texts = JSON.parse(texts);
    } catch (err) {
      // ctx.logger.error('texts incorrect format', texts);
    }
    if (Number(by_word) === 0) {
      by_word = false;
    } else {
      by_word = true;
    }
    if (!Array.isArray(texts)) {
      return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'texts must be array' });
    }
    try {
      categorie_ids = JSON.parse(categorie_ids);
    } catch (err) {
      ctx.logger.error('categorie_ids incorrect format', categorie_ids);
    }
    if (Array.isArray(categorie_ids)) {
      categorie_ids = Array.from(new Set(categorie_ids));
      for (let i = 0; i < categorie_ids.length; i++) {
        if (await service.tortious.existsTortious(categorie_ids[i])) {
          categorie_ids.splice(i, 1);
          i--;
        }
      }
      if (categorie_ids.length <= 0) {
        return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'current categorie_ids does not exist at all' });
      }
    } else {
      return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'categorie_ids must be array' });
    }
    if (!source) {
      source = ctx.app.config.erpSite;
    }
    for (const text of texts) {
      if (!(text.key && typeof text.key === 'string')) {
        return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'text.key must be string' });
      }
      if (!(text.text && typeof text.text === 'string')) {
        return ctx.json({ errcode: this.ctx.ERRCODE.DATA_ERROR, message: 'text.text must be string' });
      }
    }
    const detectionData = { callback_url, categorie_ids, source, texts, by_word };
    const sign = crypto.createHash('md5').update(JSON.stringify(detectionData)).digest('hex');
    detectionData.sign = sign;
    await ctx.app.multiQueue.add('tortious-worker-multi', detectionData, {
      removeOnComplete: true,
      jobId: sign,
    });
    ctx.json({ errcode: this.ctx.ERRCODE.NORMAL, message: 'success', data: { sign } });
  }


  /**
     *@api {get} /check-info/:sign 检测结果(异步)
     *@apiName infringement-info
     *@apiDescription 检测包含哪些侵权词(保留两天内的数据)  sign  参数签名
     *@apiGroup Tortious
     *@apiSuccess {int} errcode  错误码
     *@apiSuccess {string} message 提示语
     *@apiSuccess {object} data 检测结果数据
     *@apiSuccess {array} data.key 文本标识对应的侵权词列表
     */
  async checkInfo() {
    const { ctx } = this;
    const sign = ctx.params.sign;
    const data = {};
    let resultInfo = await ctx.app.redis.get(`detection-result:${sign}`) || '{}';
    resultInfo = JSON.parse(resultInfo);
    for (const [ key, info ] of Object.entries(resultInfo)) {
      data[key] = Object.keys(info);
    }
    ctx.json({ errcode: this.ctx.ERRCODE.NORMAL, message: 'success', data, process: process.pid });
  }


  async addTest() {
    const { ctx, service } = this;
    const body = ctx.request.body;
    const response = await service.tortious.changeTortious(body.response);
    ctx.json(response);
  }


}
module.exports = InfringementCheckController;
